package com.imc.domain;

import java.util.Date;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.Entity;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
import javax.persistence.DiscriminatorType;
import javax.persistence.GeneratedValue;
import javax.persistence.Column;
import org.apache.commons.lang.Validate;

/**
 * Defines the minimum information needed for a single person.
 * 
 * This class holds the name and surname as a string, the application-wide
 * person id, a long that identifies the user in the scope of the application.
 * 
 * This is mapped as an entity in hibernate.
 * 
 */
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "person_type", discriminatorType = DiscriminatorType.STRING)
@Table(name = "person")
public abstract class Person implements java.io.Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * The length in characters of the person name.
	 */
	private static final int PERSON_COMPLETE_NAME = 100;

	/**
	 * The length in characters of the person surname.
	 */
	private static final int PERSON_SURNAME = 50;

	/**
	 * The length in characters of the person surname.
	 */
	private static final int PERSON_ADDRESS = 50;

	/**
	 * The length in characters of the person phone number.
	 */
	private static final int PHONE_NUMBER = 30;

	/**
	 * The length in characters of the person mobile phone number.
	 */
	private static final int MOBILE_PHONE_NUMBER = 30;

	/**
	 * The length in characters of the person email.
	 */
	private static final int EMAIL_LENGTH = 100;

	/**
	 * The id of the person. This is 0 for a newly created person.
	 */
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", nullable = false)
	private long id = 0;

	/**
	 * The name of the user.
	 */
	@Column(name = "name", nullable = false, length = PERSON_COMPLETE_NAME)
	private String name;

	/**
	 * The name of the user.
	 */
	@Column(name = "surname", nullable = false, length = PERSON_SURNAME)
	private String surname;

	/**
	 * The birth date.
	 */
	@Column(name = "birth_date", nullable = false)
	private Date birthDate;

	/**
	 * The name of the user.
	 */
	@Column(name = "address", nullable = false, length = PERSON_ADDRESS)
	private String address;

	/**
	 * The phone number .
	 */
	@Column(name = "phone_number", nullable = true, length = PHONE_NUMBER)
	private String phoneNumber;

	/**
	 * The phone number .
	 */
	@Column(name = "mobile_phone_number", nullable = true, length = MOBILE_PHONE_NUMBER)
	private String mobilePhoneNumber;

	/**
	 * The phone number .
	 */
	@Column(name = "email", nullable = true, length = EMAIL_LENGTH)
	private String email;

	Person() {
	}

	/**
	 * A custom constructor.
	 * 
	 * Builds a person with the most basic data it needs to have.
	 * 
	 * @param name
	 *            The person name. It cannot be null.
	 * @param surname
	 *            The person surname. It cannot be null.
	 * @param birthDate
	 *            The person birth date. It cannot be null.
	 * @param address
	 *            The person address. It cannot be null.
	 */
	public Person(final String name, final String surname,
			final Date birthDate, final String address) {
		Validate.notNull(name, "The  name cannot be null");
		Validate.notNull(surname, "The surname cannot be null");
		Validate.notNull(birthDate, "The birth date cannot be null");
		Validate.notNull(address, "The address cannot be null");

		this.name = name;
		this.surname = surname;
		this.birthDate = birthDate;
		this.address = address;

	}

	/**
	 * A full constructor.
	 * 
	 * Builds a person with all it information.
	 * 
	 * @param name
	 *            The person name. It cannot be null.
	 * @param surname
	 *            The person surname. It cannot be null.
	 * @param birthDate
	 *            The person birth date. It cannot be null.
	 * @param address
	 *            The person address. It cannot be null.
	 * @param mobilePhone
	 *            The person mobile phone number.
	 * @param phone
	 *            The person phone number.
	 * @param email
	 *            The person email address.
	 */
	public Person(final String name, final String surname,
			final Date birthDate, final String address,
			final String mobilePhone, final String phone, final String email) {
		Validate.notNull(name, "The  name cannot be null");
		Validate.notNull(surname, "The surname cannot be null");
		Validate.notNull(birthDate, "The birth date cannot be null");
		Validate.notNull(address, "The address cannot be null");

		this.name = name;
		this.surname = surname;
		this.birthDate = birthDate;
		this.address = address;
		this.email = email;
		this.phoneNumber = phone;
		this.mobilePhoneNumber = mobilePhone;
	}

	/**
	 * Returns the id of the person.
	 * 
	 * @return Returns the person id.
	 */
	public long getId() {
		return id;
	}

	/**
	 * Returns the name of the person.
	 * 
	 * @return Returns the person name.
	 */
	public String getName() {
		return name;
	}

	/**
	 * Modifies the values of the person name.
	 * 
	 * @param name
	 *            The name of the person. It cannot be null.
	 */
	public void setName(String name) {
		Validate.notNull(name, "The person name cannot be null");
		this.name = name;
	}

	/**
	 * Returns the surname of the person.
	 * 
	 * @return Returns the person surname.
	 */
	public String getSurname() {
		return surname;
	}

	/**
	 * Modifies the values of the person surname.
	 * 
	 * @param surname
	 *            The name of the person. It cannot be null.
	 */
	public void setSurname(String surname) {
		Validate.notNull(surname, "The person surname cannot be null");
		this.surname = surname;
	}

	/**
	 * Returns the person birth date.
	 * 
	 * @return Returns the person birth date.
	 */
	public Date getBirthDate() {
		return birthDate;
	}

	/**
	 * Modifies the values of the person birth date.
	 * 
	 * @param birthDate
	 *            The birth date of the person. It cannot be null.
	 */
	public void setBirthDate(Date birthDate) {
		Validate.notNull(birthDate, "The birth date cannot be null");
		this.birthDate = birthDate;
	}

	/**
	 * Returns the person phone number .
	 * 
	 * @return Returns the person phone number.
	 */
	public String getPhoneNumber() {
		return phoneNumber;
	}

	/**
	 * Modifies the values of the person phone number.
	 * 
	 * @param phoneNumber
	 *            The phone number of the person.
	 */
	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	/**
	 * Returns the person mobile phone number .
	 * 
	 * @return Returns the person mobile phone number.
	 */
	public String getMobilePhoneNumber() {
		return mobilePhoneNumber;
	}

	/**
	 * Modifies the values of the person mobile phone number.
	 * 
	 * @param mobilePhoneNumber
	 *            The mobile phone number of the person.
	 */
	public void setMobilePhoneNumber(String mobilePhoneNumber) {
		this.mobilePhoneNumber = mobilePhoneNumber;
	}

	/**
	 * Returns the person email .
	 * 
	 * @return Returns the person email.
	 */
	public String getEmail() {
		return email;
	}

	/**
	 * Modifies the values of the person email.
	 * 
	 * @param email
	 *            The email of the person.
	 */
	public void setEmail(String email) {
		this.email = email;
	}

	/**
	 * Modifies the values of the person address.
	 * 
	 * @param address
	 *            The address of the person.
	 */
	public void setAddress(String address) {
		this.address = address;
	}

	/**
	 * Returns the person address .
	 * 
	 * @return Returns the person address.
	 */
	public String getAddress() {
		return address;
	}

}
